package com.ruoyi.common.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.ruoyi.common.utils.file.FileUploadUtils;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

@Component
public class QRCodeUtils {

    private static final int BLACK = 0xFF000000;
    private static final int WHITE = 0xFFFFFFFF;
    private static final int WIDTH = 300;
    private static final int HEIGHT = 300;

    /**
     * 把生成的二维码存入到图片中
     * @param matrix zxing包下的二维码类
     * @return
     */
    public static BufferedImage toBufferedImage(BitMatrix matrix) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
            }
        }
        return image;
    }
    /**
     * 生成二维码并写入文件
     * @param content 扫描二维码的内容
     * @param format 图片格式 jpg
     * @param file  文件
     * @throws Exception
     */
    public static void writeToFile(String content, String format, File file)
            throws Exception {
        MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
        @SuppressWarnings("rawtypes")
        Map hints = new HashMap();
        //设置UTF-8， 防止中文乱码
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        //设置二维码四周白色区域的大小
        hints.put(EncodeHintType.MARGIN,5);
        //设置二维码的容错性
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        //画二维码
        BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, WIDTH, HEIGHT, hints);
        BufferedImage image = toBufferedImage(bitMatrix);
        if (!ImageIO.write(image, format, file)) {
            throw new IOException("Could not write an image of format " + format + " to " + file);
        }
    }

    /**
     * 给二维码图片加上文字
     * @param pressText 文字
     * @param qrFile  二维码文件
     * @param fontStyle
     * @param color
     * @param fontSize
     */
    public static void pressText(String pressText, File qrFile, int fontStyle, Color color, int fontSize) throws Exception {
        pressText = new String(pressText.getBytes(), "utf-8");
        Image src = ImageIO.read(qrFile);
        int imageW = src.getWidth(null);
        int imageH = src.getHeight(null);
        BufferedImage image = new BufferedImage(imageW, imageH, BufferedImage.TYPE_INT_RGB);
        Graphics g = image.createGraphics();
        g.drawImage(src, 0, 0, imageW, imageH, null);
        //设置画笔的颜色
        g.setColor(color);
        //设置字体
        Font font = new Font("微软雅黑", fontStyle, fontSize);
        FontMetrics metrics = g.getFontMetrics(font);
        //文字在图片中的坐标 这里设置在中间
        int startX = (WIDTH - metrics.stringWidth(pressText)) / 2;
        int startY = HEIGHT-16;
        g.setFont(font);
        g.drawString(pressText, startX, startY);
        g.dispose();
        FileOutputStream out = new FileOutputStream(qrFile);
        ImageIO.write(image, "JPEG", out);
        out.close();
    }

    @Value("${base.uploadPath}")
    private String uploadPath;
    @Value("${vqms.uploadPath}")
    private String vqmsUploadPath;

    /**
     * 生成二维码（带中文）
     * @param ruleUrl 规则url
     * @param text 中文
     * @return
     */
    public String createQRCode(String ruleUrl,String text){
        try {
            //生成的二维码的临时路径
            String QR_CODE_IMAGE_PATH = uploadPath+ "/qrcode.jpg";
            File qrcFile = new File(uploadPath,"qrcode.jpg");
            QRCodeUtils.writeToFile(ruleUrl, "jpg", qrcFile);
            QRCodeUtils.pressText(text, qrcFile, 5, Color.BLACK, 18);
            // 调用若依上传组件，上传二维码并返回新文件名称,例子：/profile/c/2024/03/14/a1806328-290d-491a-ac00-de09219d9928.png
            String fileName2 = FileUploadUtils.upload(vqmsUploadPath, file2MultipartFile(QR_CODE_IMAGE_PATH)).replaceAll("/profile/c/","");
            return fileName2;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * MultipartFile 转 File
     *
     * @param path
     * @return
     */
    public static MultipartFile file2MultipartFile(String path) {
        File file = new File(path);
        MultipartFile multipartFile;
        try {
            DiskFileItem fileItem2 = (DiskFileItem) new DiskFileItemFactory().createItem("file", "multipart/form-data", true, file.getName());
            Files.copy(Paths.get(file.getAbsolutePath()), fileItem2.getOutputStream());
            multipartFile = new CommonsMultipartFile(fileItem2);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return multipartFile;
    }

}
